#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include "mxml.h"
#include "Base.h"
#include "Net.h"
#include "XmlParser.h"

//static char ipaddr[]="124.42.50.10";

ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
	struct msghdr	msg;
	struct iovec	iov[1];

	union {
	  struct cmsghdr	cm;
	  char				control[CMSG_SPACE(sizeof(int))];
	} control_un;
	struct cmsghdr	*cmptr;

	msg.msg_control = control_un.control;
	msg.msg_controllen = sizeof(control_un.control);

	cmptr = CMSG_FIRSTHDR(&msg);
	cmptr->cmsg_len = CMSG_LEN(sizeof(int));
	cmptr->cmsg_level = SOL_SOCKET;
	cmptr->cmsg_type = SCM_RIGHTS;
	*((int *) CMSG_DATA(cmptr)) = sendfd;

	msg.msg_name = NULL;
	msg.msg_namelen = 0;

	iov[0].iov_base = ptr;
	iov[0].iov_len = nbytes;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;

	return(sendmsg(fd, &msg, 0));
}

ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
	struct msghdr	msg;
	struct iovec	iov[1];
	ssize_t			n;

	union {
	  struct cmsghdr	cm;
	  char				control[CMSG_SPACE(sizeof(int))];
	} control_un;
	struct cmsghdr	*cmptr;

	msg.msg_control = control_un.control;
	msg.msg_controllen = sizeof(control_un.control);

	msg.msg_name = NULL;
	msg.msg_namelen = 0;

	iov[0].iov_base = ptr;
	iov[0].iov_len = nbytes;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;

	if ( (n = recvmsg(fd, &msg, 0)) <= 0)
		return(n);

	if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
	    cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
		if (cmptr->cmsg_level != SOL_SOCKET)
              {      
			dbg("control level != SOL_SOCKET");
                     return -1;
              }
		if (cmptr->cmsg_type != SCM_RIGHTS)
              {      
			dbg("control type != SCM_RIGHTS");
                      return -1;
              }
		*recvfd = *((int *) CMSG_DATA(cmptr));
	} else
		*recvfd = -1;		/* descriptor was not passed */

	return(n);
}

int NetSendSocketFd(int sendfd,enum NETTYPE nettype,char* cmd_buff,int cmd_len)
{
        int sockfd,ret = -1;
        struct sockaddr_un addr;
	char buf[10];
	buf[0]=(char)nettype;

	if(cmd_len<0)
		{
		return ret;
		}
	if(cmd_len>0)
		{
		memcpy((buf+1),cmd_buff,cmd_len);
		
		}
	
        char c = (char)nettype;

	LOGINFO("------------- netsend socket fd --------type:%c ----\n",nettype);
        sockfd=socket(AF_UNIX,SOCK_STREAM,0);
        if(sockfd<0)
        {
              return -1;
        }
			//LOGINFO("------------- netsend socket fd 1 --------type:%c ----\n",nettype);

        bzero((void*)&addr,sizeof(struct sockaddr_un));
        addr.sun_family=AF_UNIX;
		if(nettype==NET_VOICE_CLIENT || nettype== NET_VOICE_MEGAEYES)
			{
			strcpy(addr.sun_path,VOICE_UNIX_PATH);
			}
		else
			{
			strcpy(addr.sun_path,UNIX_PATH);
			}
        	//LOGINFO("------------- netsend socket fd  2--------type:%c ----\n",nettype);

        ret = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
        if (ret < 0)
        {
        	close(sockfd);
        	LOGERROR("connect error \n");
            return -1;
        }
	
	LOGINFO("[%d] Receive connection %d\n", getpid(), sendfd);
	ret = write_fd(sockfd, &buf, cmd_len+1, sendfd);  
       close(sockfd);
        
        return ret;
}

/* --------------------------------------------------------------------------*/
/** 
 * @Synopsis  
 * 
 * @Param len
 * @Param code
 * @Param seq
 * @Param flags
 * 
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
VSP_RECVHEADER InitVSP_RECVHeader(int len, int code, int seq, int flags )
{
	VSP_RECVHEADER hdr;
    hdr.version = 257;
    hdr.xmlLen = len;
    hdr.cmdCode = code;
    hdr.cmdSeq = seq;
	hdr.flags = flags;
    return hdr;
}


/* --------------------------------------------------------------------------*/
/** 
 * @Synopsis  set scoket options(clifd's socket options inherit from sockfd)
 * 
 * @Param sockfd
 */
/* ----------------------------------------------------------------------------*/
void SetSockOptions(int fd)
{
	int sockfd = fd;
	int optkeepAlive = 1;
	if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&optkeepAlive, sizeof(int)) == -1)
	{
		printf("setsockopt SO_KEEPALIVE error!\n");
		return;
	}

	bool optReuseaddr = TRUE; 
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const   char*)&optReuseaddr,sizeof(bool)) == -1)   
	{
		printf("setsockopt SO_REUSEADDR error!\n");
		return;
	}
	int optRecvBuf = 1024*1024;
	if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (const   char*)&optRecvBuf, sizeof(int)) == -1)
	{
		printf("setsockopt SO_RCVBUF error!\n");
		return;
	}

	int optSendBuf = 0;//1024*1024;
    if(setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const   char*)&optSendBuf, sizeof(int)) == -1)
	{
		printf("setsockopt SO_SNDBUF error!\n");
		return;
	}

	int on = 1;
	if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,&on,sizeof(on)) == -1)
	{
		printf("setsockopt TCP_NODELAY error!\n");
		return;
	}

}





